#include    "I2C.h"

void I2C_Init(void)
{
    gpio_config_t i2c_gpio_config = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_OUTPUT,
        .pull_down_en = 0,
        .pull_up_en = 1,
        .pin_bit_mask = (1ULL << I2C_SDA_PIN) | (1ULL << I2C_SCL_PIN)
    };
    gpio_config(&i2c_gpio_config);
}

static void I2C_Start(void)
{
    I2C_SDA_OUT();
    I2C_SDA_H();
    I2C_SCL_H();
    DelayMs(1);
    I2C_SDA_L();
    DelayMs(1);
    I2C_SCL_L();
    DelayMs(1);
}

static void I2C_Stop(void)
{
    I2C_SDA_OUT();
    I2C_SCL_L();
    I2C_SDA_L();
    DelayMs(1);
    I2C_SCL_H();
    DelayMs(1);
    I2C_SDA_H();
    DelayMs(1);
}

static void I2C_Write_Byte(uint8_t data)
{
    uint8_t i;
    I2C_SDA_OUT();
    for (i = 0; i < 8; i++)
    {
        if (data & 0x80)
        {
            I2C_SDA_H();
        }
        else
        {
            I2C_SDA_L();
        }
        data <<= 1;
        I2C_SCL_H();
        DelayMs(1);
        I2C_SCL_L();
        DelayMs(1);
    }
}

static uint8_t I2C_Read_Byte(void)
{
    uint8_t i, data = 0;
    I2C_SDA_IN();
    for (i = 0; i < 8; i++)
    {
        I2C_SCL_H();
        DelayMs(1);
        data <<= 1;
        if (I2C_SDA_READ())
        {
            data |= 0x01;
        }
        I2C_SCL_L();
        DelayMs(1);
    }
    return data;
}

static uint8_t I2C_Wait_Ack(void)
{
    uint8_t i;
    I2C_SDA_H();
    I2C_SDA_IN();
    I2C_SCL_H();
    DelayMs(1);
    for (i = 0; i < 255; i++)
    {
        if (!I2C_SDA_READ())
        {
            break;
        }
    }
    I2C_SCL_L();
    DelayMs(1);
    if (i == 255)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

static void I2C_Ack(void)
{
    I2C_SCL_L();
    I2C_SDA_OUT();
    I2C_SDA_L();
    DelayMs(1);
    I2C_SCL_H();
    DelayMs(1);
    I2C_SCL_L();
    DelayMs(1);
}

static void I2C_NAck(void)
{
    I2C_SCL_L();
    I2C_SDA_OUT();
    I2C_SDA_H();
    DelayMs(1);
    I2C_SCL_H();
    DelayMs(1);
    I2C_SCL_L();
    DelayMs(1);
}

void I2C_Read(uint8_t slave_addr, uint8_t *data)
{
    // I2C_Start();
    // I2C_Write_Byte(slave_addr);
    // if (I2C_Wait_Ack())
    // {
    //     I2C_Stop();
    //     return 0;
    // }
    // I2C_Write_Byte(reg_addr);
    // if (I2C_Wait_Ack())
    // {
    //     I2C_Stop();
    //     return 0;
    // }
    I2C_Start();
    I2C_Write_Byte(slave_addr + 1);
    if (I2C_Wait_Ack())
    {
        I2C_Stop();
        return;
    }
    data[0] = I2C_Read_Byte();
    I2C_Ack();
    data[1] = I2C_Read_Byte();
    I2C_NAck();
    I2C_Stop();
}